<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    
</body>
</html>
<script>
    // 字符串的解构赋值
    // 字符串也可以解构赋值 此时 字符串被转换成了一个类似数组的对象
    const [a, b, c, d, e] = 'hello';
    a // "h"
    b // "e"
    c // "l"
    d // "l"
    e // "o"

    // 类似数组的对象都有一个length属性 可以对这个属性进行解构赋值
    let {length : len} = 'hello';
    len // 5

    // 数值和布尔值的解构赋值
    // 解构赋值时 如果等号右边是数值和布尔值 则会先转为对象
    let {toString: s} = 123;
    s === Number.prototype.toString // true

    let {toString: s} = true;
    s === Boolean.prototype.toString // true

    // 解构赋值的规则是 只要等号右边的值不是对象或者数组 就先将其转换成对象 
    // 由于undefined和null无法转换成对象 所以对它们解构赋值会报错
    let { prop: x } = undefined; // TypeError
    let { prop: y } = null; // TypeError

    // 函数参数的解构赋值
    function add([x, y]){
        return x + y;
    }

    add([1, 2]); // 3

    // 再举一个例子
    [[1, 2], [3, 4]].map(([a, b]) => a + b);
    // [ 3, 7 ]

    // 函数参数的解构也可以使用默认值
    function move({x = 0, y = 0} = {}) {
        return [x, y];
    }

    move({x: 3, y: 8}); // [3, 8]
    move({x: 3}); // [3, 0]
    move({}); // [0, 0]
    move(); // [0, 0]

    // 注意对比上下的写法
    function move({x, y} = { x: 0, y: 0 }) {
        return [x, y];
    }

    move({x: 3, y: 8}); // [3, 8]
    move({x: 3}); // [3, undefined]
    move({}); // [undefined, undefined]
    move(); // [0, 0]




    // 变量解构的用途
    // 交换变量的值
    let x = 1;
    let y = 2;

    [x, y] = [y, x];

    // 函数返回多个值

    // 返回一个数组
    function example() {
        return [1, 2, 3];
    }
    let [a, b, c] = example();

    // 返回一个对象

    function example() {
        return {
            foo: 1,
            bar: 2
        };
    }
    let { foo, bar } = example();

    // 解构赋值可以方便地将一组参数与变量名对应起来
    // 参数是一组有次序的值
    function f([x, y, z]) {}
    f([1, 2, 3]);

    // 参数是一组无次序的值
    function f({x, y, z}) {}
    f({z: 3, y: 2, x: 1});


    // 提取JSON数据
    let jsonData = {
        id: 42,
        status: "OK",
        data: [867, 5309]
    };
    let { id, status, data: number } = jsonData;
    console.log(id, status, number);
    // 42, "OK", [867, 5309]


    // 函数参数的默认值

    // 遍历Map对象
    // 任何部署了Iterator接口的对象 都可以用for...of循环遍历
    // Map解构原生支持Iterator接口 配合变量的解构赋值 获取键名和键值非常方便
    const map = new Map();
    map.set('first', 'hello');
    map.set('second', 'world');

    for (let [key, value] of map) {
        console.log(key + " is " + value);
    }
    // first is hello
    // second is world


    // 获取键名
    for (let [key] of map) {
        // ...
    }

    // 获取键值
    for (let [,value] of map) {
        // ...
    }

    // 输入模块的指定方法
    const { SourceMapConsumer, SourceNode } = require("source-map");

</script>